package com.gitee.neuray.security.generator.strategy;

import com.gitee.neuray.security.common.entity.BaseEntity;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.lang.StringUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.springframework.objenesis.instantiator.basic.ObjectInputStreamInstantiator;

import javax.persistence.Column;
import java.io.File;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: zhhongyu
 * @description: 单表代码生成实现策略
 * @since: Create in 13:14 2020/2/19
 */
public class GenSingleTableStrategy extends GenerateStrategy{
    @Override
    public VelocityContext getVelocityContext(Configuration config,
                                     GenBaseBizEntityStrategy bizParams,
                                     Map<String,String> table,
                                     List<Map> columns) {
        boolean hasBigDecimal = false;
        GenBaseTableEntityStrategy tableEntity = getTableEntity(bizParams, table);
        List<GenBaseColumnEntityStrategy> allcolumn = getColumns(columns, config, tableEntity, hasBigDecimal);
        List<Map> bizColumns = getBizColumns(columns);
        //不包含基类的业务代码
        List<GenBaseColumnEntityStrategy> bizColumnEntitys = getColumns(bizColumns, config, tableEntity, hasBigDecimal);
        tableEntity.setColumns(allcolumn);
        //没主键，则第一个字段为主键
        if (tableEntity.getPk() == null) {
            tableEntity.setPk(tableEntity.getColumns().get(0));
        }
        //设置velocity资源加载器
        Properties prop = new Properties();
        prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        Velocity.init(prop);
        //封装模板数据
        Map<String, Object> map = getMap(tableEntity);
        map.put("pk", tableEntity.getPk());
        map.put("columns", tableEntity.getColumns());
        map.put("bizColumns",bizColumnEntitys);
        map.put("hasBigDecimal", hasBigDecimal);
        map.putAll(getVueContextMap(config,bizParams));
        VelocityContext context = new VelocityContext(map);
        return context;
    }

    @Override
    public List<String> getTemplates() {
        List<String> templates = new ArrayList<String>();
        templates.add("template/singletable/Entity.java.vm");
        templates.add("template/singletable/Mapper.java.vm");
        templates.add("template/singletable/Mapper.xml.vm");
        templates.add("template/singletable/Biz.java.vm");
        templates.add("template/singletable/Controller.java.vm");
        templates.add("template/singletable/PageExcelVo.java.vm");
        templates.addAll(getVueTemplate());
        return templates;
    }

    @Override
    public String getFileName(String template, String className, String packageName, String moduleName,String vuePath,String serverName) {
        String packagePath = "main" + File.separator + "java" + File.separator;
        if (StringUtils.isNotBlank(packageName)) {
            packagePath += packageName.replace(".", File.separator) + File.separator ;
        }
        if(StringUtils.isNotBlank(serverName)){
            packagePath += serverName + File.separator;
        }
        if(StringUtils.isNotBlank(moduleName)){
            packagePath += moduleName + File.separator;
        }

        if (template.contains("Entity.java.vm")) {
            return packagePath + "entity" + File.separator + className + "Entity.java";
        }

        if (template.contains("Mapper.java.vm")) {
            return packagePath + "mapper" + File.separator + className + "Mapper.java";
        }
        if (template.contains("Biz.java.vm")) {
            return packagePath + "biz" + File.separator + className + "Biz.java";
        }
        if (template.contains("PageExcelVo.java.vm")) {
            return packagePath + "vo" + File.separator + className + "PageExcelVo.java";
        }

        if (template.contains("Controller.java.vm")) {
            return packagePath + "controller" + File.separator + className + "Controller.java";
        }

        if (template.contains("Mapper.xml.vm")) {
            return "main" + File.separator + "resources" + File.separator + "mapper" + File.separator + moduleName + File.separator + className + "Mapper.xml";
        }
        //配置vue路径
        if(template.contains("vm2.vue.vm")){
            return vuePath + File.separator + serverName + File.separator + moduleName + File.separator + className.toLowerCase() + ".vue";
        }
        return null;
    }
    private List<Map> getBizColumns(List<Map> columns){
        Field[] declaredFields = BaseEntity.class.getDeclaredFields();
        List<String> baseEntityDeclares = new ArrayList<>();
        for(Field field : declaredFields){
            Column declaredAnnotation = field.getDeclaredAnnotation(Column.class);
            String name = declaredAnnotation.name();
            baseEntityDeclares.add(name);
        }
        List<Map> collect = columns.stream().filter(map -> {
            String columnName = (String) map.get("columnName");
            return !baseEntityDeclares.parallelStream().anyMatch(baseColumn -> Objects.equals(columnName, baseColumn));
        }).collect(Collectors.toList());
        return collect;
    }

}
